<template>
  <el-container class="group-capsule" direction="vertical" :style="{ 'height': height }">
    <el-scrollbar class="scrollbar" height="100%">
      <el-row class="search-input">
        <el-input
          placeholder="搜索"
          size="large"
          v-model.trim="data.searchStr"
        >
          <template #append>
            <el-button
              class="search-btn"
              type="info"
              @click="search"
              icon="Search"
              title="点击搜索">
            </el-button>
          </template>
        </el-input>
      </el-row>
      <el-row class="groups">
        <template v-if="data.groups.length > 0">
          <group-item
            v-for="group in data.groups"
            :key="group.id"
            :group="group"
            :isSelected="curSelectedGroupId === group.id"
            :folders="data.folders"
            @changeCurGroup="changeCurGroup"
            @updateGroup="updateGroup"
            @openFolderDialog="openFolderDialog"
            @resetAllGroupItem="resetAllGroupItem"
            @reReq="getGroupAndFolder"
            ref="groupItems">
          </group-item>
        </template>
        <p
          v-else-if="data._groups.length === 0"
          style="margin: 30px 0; width: 100%; text-align: center; color: #909399; font-size: 12px;"
        >
          暂无分组
        </p>
        
      </el-row>
      <el-divider style="margin: 5px 15px;" v-if="data.folders.length > 0"></el-divider>
      <el-row class="folders">
        <el-menu background-color="transparent" active-text-color="#2c3e50" v-if="data.folders.length > 0">
          <el-sub-menu
            v-for="(folder, findex) in data.folders"
            :key="folder.id"  
            :index="`${findex}`"
            @contextmenu.prevent=""
          >
            <template #title>
                <el-icon><Folder /></el-icon><span>{{ folder.fname }}</span>
            </template>
            <el-menu-item
              v-for="(group, gindex) in folder.groups"
              :key="group.id"
              :index="`${findex}-${gindex}`"
            >
              <group-item
                :group="group"
                :isSelected="curSelectedGroupId === group.id"
                :folders="data.folders"
                @changeCurGroup="changeCurGroup"
                @updateGroup="updateGroup"
                @openFolderDialog="openFolderDialog"
                @resetAllGroupItem="resetAllGroupItem"
                @reReq="getGroupAndFolder"
                ref="groupItems">
              </group-item>
            </el-menu-item>
          </el-sub-menu>
        </el-menu>
      </el-row>
      <div style="margin-bottom: 10rem;"></div>
    </el-scrollbar>
    <el-row class="bottom-bar">
      <el-dropdown
        style="flex-grow: 1;"
        size="large"
        placement="top"
        trigger="click"
      >
        <el-button class="addGroup-btn"><el-icon><plus /></el-icon>文件夹管理</el-button>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item @click="openDrawer(DRAWERTYPE.FOLDER)">新建文件夹</el-dropdown-item>
            <el-dropdown-item @click="openDrawer(DRAWERTYPE.DELETEFOLDER)">删除文件夹</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
      <el-tooltip
        popper-class="btn-popper"
        placement="top-end"
        width="auto"
        trigger="hover"
        content="新建分组"
      >
        <el-button class="addFolder-btn" @click="openDrawer(DRAWERTYPE.GROUP)">
          <el-icon><edit /></el-icon>
        </el-button>
      </el-tooltip>
    </el-row>
    <el-dialog
      v-model="data.dialogVisible"
      width="50%"
    >
      <template #header>
        <h3 style="text-align: left;">
          移动"{{ getNeedMoveToFolderGroupName?.gname }}"分组到文件夹
        </h3>
      </template>
      <el-row class="dialog-content">
        <el-table
          :data="data.folders"
          style="width: 100%"
          stripe
          :header-cell-style="{ 'text-align': 'center' }"
          :cell-style="{ 'text-align': 'center' }"
          highlight-current-row
        >
          <el-table-column prop="fname" label="文件夹名称" />
          <el-table-column prop="descr" label="描述" />
          <el-table-column prop="createTime" label="创建时间" />
          <el-table-column label="操作">
            <template #default="{ row }">
              <el-button type="text" @click="moveGroupToFolder(row.id, row.fname)">移动到这里</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-row>
      <template #footer>
        <span class="dialog-footer">
          <el-button
            type="text"
            @click="moveGroupToFolder(-1, '')"
            v-if="getNeedMoveToFolderGroupName?.folderId"
          >
            移出文件夹
          </el-button>
          <el-button type="primary" @click="data.dialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    <el-drawer
      v-model="data.drawer"
      :title="{
        [DRAWERTYPE.FOLDER]: '新建文件夹',
        [DRAWERTYPE.GROUP]: '新建分组',
        [DRAWERTYPE.DELETEFOLDER]: '删除文件夹'
      }[data.drawerType]"
      direction="ltr"
      @close="resetForm"
    >
      <el-row class="drawer-content" v-show="data.drawerType === DRAWERTYPE.GROUP">
        <el-col>
          <el-form
            ref="createGroupFormRef"
            :model="createGroupForm"
            label-width="90px"
            size="default"
            style="width: 100%"
            :rules="createGroupFormRules"
          >
            <el-form-item prop="gname" label="分组名称:">
              <el-input v-model="createGroupForm.gname"></el-input>
            </el-form-item>
            <el-form-item prop="descr" label="分组描述:">
              <el-input v-model="createGroupForm.descr"></el-input>
            </el-form-item>
            <el-form-item prop="icon" label="选择图标:">
              <el-select
                v-model="createGroupForm.icon"
                style="width: 100%;"
                placeholder="图标"
                clearable
              >
                <el-option
                  v-for="icon in icons"
                  :key="icon"
                  :label="icon"
                  :value="icon"
                >
                  <el-icon style="transform: translate(0, 2px)"><component :is="icon" /></el-icon>
                  - {{ icon }}
                </el-option>
              </el-select>
            </el-form-item>
          </el-form>
        </el-col>
        <el-col class="folder-tag" v-if="data.folders.length > 0">
          <div class="title">添加到文件夹:</div>
          <div class="tag-box">
            <el-tag
              v-for="folder in data.folders"
              :key="folder.id"
              size="large"
              type="info"
              @click="selectFolder(folder.id)"
              :class="{
                'tag': true,
                'active': folder.id === createGroupForm.folderId
              }"
            >
              {{ folder.fname }}
            </el-tag>
          </div>
        </el-col>
        <el-col style="text-align: right">
          <el-button
            type="primary"
            plain
            size="default"
            style="width: 80px"
            @click="createGroup"
            :loading="data.drawerBtnLoading">确定
          </el-button>
        </el-col>
      </el-row>
      <el-row class="drawer-content" v-show="data.drawerType === DRAWERTYPE.FOLDER">
        <el-col>
          <el-form
            ref="createFolderFormRef"
            :model="createFolderForm"
            label-width="100px"
            size="default"
            style="width: 100%"
            :rules="createFolderFormRules"
          >
            <el-form-item prop="fname" label="文件夹名称:">
              <el-input v-model="createFolderForm.fname"></el-input>
            </el-form-item>
            <el-form-item prop="descr" label="文件夹描述:">
              <el-input v-model="createFolderForm.descr"></el-input>
            </el-form-item>
          </el-form>
        </el-col>
        <el-col style="text-align: right">
          <el-button
            type="primary"
            plain
            size="default"
            @click="createFolder"
            style="width: 80px"
            :loading="data.drawerBtnLoading">确定
          </el-button>
        </el-col>
      </el-row>
      <el-row class="drawer-content" v-show="data.drawerType === DRAWERTYPE.DELETEFOLDER">
        <el-col style="margin-bottom: 20px;">
          <p style="text-align: left; font-size: .9rem;">
            {{ data.folders.length > 0 ? '请选择要删除的文件夹:' : '暂无文件夹数据' }}
          </p>
        </el-col>
        <el-checkbox-group
          v-if="data.folders.length > 0 "
          style="text-align: left; margin-bottom: 40px;"
          v-model="deleteFolderChecked"
        >
          <el-checkbox
            v-for="folder in data.folders"
            :key="folder.id"
            size="large"
            border
            :label="folder.id"
            style="margin: 0 10px 10px 0;"
          >
            {{ folder.fname }}
          </el-checkbox>
        </el-checkbox-group>
        <el-col style="text-align: right" v-if="data.folders.length > 0 ">
          <el-button
            type="primary"
            plain
            size="default"
            @click="deleteFolder"
            style="width: 80px"
            :loading="data.drawerBtnLoading">删除
          </el-button>
        </el-col>
      </el-row>
    </el-drawer>
  </el-container>
</template>

<script lang="ts" setup>
import { ref, reactive, computed, onBeforeUnmount, nextTick } from 'vue'
import { SUCCESS_CODE } from '@/config/requestCode'
import type { Group, Folder } from '@/types/types'
import { getGroupAndFolderApi } from '&/user'
import { moveGroupToFolderApi, addGroupApi } from '&/group'
import { addFolderApi, deleteFolderApi } from '&/folder'
import { searchTodo } from '&/todo'
import loading from '@/utils/globalLoading'
import GroupItem from './groupItem.vue'
import { openMessage, openConfirmMessageBox } from '@/utils/elComponents'
import { supportIcons as icons } from '@/utils/elementPlusIcon'
import { FormInstance, FormRules } from 'element-plus'
import { bus } from '@/utils/util'

const {
  height = '60px',
  curSelectedGroupId,
  changeCurGroup
} = defineProps<{
  height: string,
  curSelectedGroupId: number,
  changeCurGroup: (groupId: number, name: string, icon: string) => void
}>()

enum DRAWERTYPE {
  GROUP,
  FOLDER,
  DELETEFOLDER
}

// data
const data = reactive<{
  _groups: Group[]
  groups: Group[],
  folders: Folder[],
  searchStr: string,
  dialogVisible: boolean,
  drawer: boolean,
  needMoveToFolderGroupId: number,
  drawerType: DRAWERTYPE,
  drawerBtnLoading: boolean
}>({
  _groups: [],
  groups: [],
  folders: [],
  searchStr: '',
  dialogVisible: false,
  drawer: false,
  needMoveToFolderGroupId: -1,
  drawerType: DRAWERTYPE.GROUP,
  drawerBtnLoading: false
})

// 新建分组
const createGroupFormRef = ref<FormInstance>()
const createGroupForm = reactive<{
  [propName: string]: any
}>({
  gname: '',
  descr: '',
  icon: '',
  folderId: null
})
const createGroupFormRules = reactive<FormRules>({
  gname: { required: true, message: '分组名称不能为空' },
  descr: { min: 0, max: 100, message: '分组描述不能超过100个字符' }
})
const createGroup = async () => {
  const result = await createGroupFormRef?.value?.validate()
  if (!result) {
    return
  }
  data.drawerBtnLoading = true
  const reqData = {
    gname: createGroupForm.gname.trim(),
    descr: createGroupForm.descr.trim(),
    icon: createGroupForm.icon,
    folderId: createGroupForm.folderId
  }
  const resp = await addGroupApi(reqData)
  if (resp && resp.code == SUCCESS_CODE) {
    data.drawer = false
    getGroupAndFolder()
    openMessage('success', '创建成功!')
  } else {
    openMessage('error', '创建失败!')
  }

  data.drawerBtnLoading = false
}

// 新建文件夹
const createFolderFormRef = ref<FormInstance>()
const createFolderForm = reactive({
  fname: '',
  descr: ''
})
const createFolderFormRules = reactive<FormRules>({
  fname: { required: true, message: '分组名称不能为空' },
  descr: { min: 0, max: 100, message: '分组描述不能超过100个字符' }
})
const createFolder = async() => {
  const result = await createFolderFormRef?.value?.validate()
  if (!result) {
    return
  }
  data.drawerBtnLoading = true
  const reqData = {
    fname: createFolderForm.fname.trim(),
    descr: createFolderForm.descr.trim(),
  }
  const resp = await addFolderApi(reqData)
  if (resp && resp.code == SUCCESS_CODE) {
    data.drawer = false
    getGroupAndFolder()
    openMessage('success', '创建成功!')
  } else {
    openMessage('error', '创建失败!')
  }
  data.drawerBtnLoading = false
}

// 删除文件夹
const deleteFolderChecked = ref([])
const deleteFolder = async () => {
  if (deleteFolderChecked.value.length === 0) {
    openMessage('warning', '请选择要删除的文件夹!')
    return
  }
  try {
    await openConfirmMessageBox('确认删除选中的文件夹吗?', '')
  } catch (e) { return }
  const resp = await deleteFolderApi(deleteFolderChecked.value)
  if (resp && resp.code == SUCCESS_CODE) {
    openMessage('success', '删除成功!')
    getGroupAndFolder()
  } else {
    openMessage('error', '删除失败!')
  } 
}

const openDrawer = (type: DRAWERTYPE) => {
  data.drawerType = type
  data.drawer = true
}
const resetForm = () => {
  createGroupForm.folderId = null
  createGroupFormRef?.value?.resetFields()
  createFolderFormRef?.value?.resetFields()
  deleteFolderChecked.value = []
}

const groupItems = ref<{
  getId: () => number,
  reset: () => void
}[] | null>(null)

const selectFolder = (folderId: number) => {
  createGroupForm.folderId = createGroupForm.folderId === folderId
    ? null
    : folderId
}

const getNeedMoveToFolderGroupName = computed(() => data
  ._groups.find(group => group.id === data.needMoveToFolderGroupId)
)

const resetAllGroupItem = (expectedId: number) => {
  groupItems?.value?.forEach(groupItem => {
    if (groupItem.getId() !== expectedId) {
      groupItem.reset()
    }
  })
}

const updateGroup = (id: number, gname: string, icon: string, descr: string,) => {
  let group = [
    ...data.groups,
    ...data.folders.map(folder => folder.groups).flat()
  ].find(group => group.id === id)
  if (!group) return
  if (gname) group.gname = gname
  if (icon) group.icon = icon 
  if (descr) group.descr = descr
}

const search = async () => {
  if (data.searchStr == '') {
    openMessage('warning', '请输入搜索关键字~~')
    return
  }

  loading.show()
  const resp = await searchTodo(data.searchStr)
  if (resp && resp.code == SUCCESS_CODE) {
    changeCurGroup(-1, `"${data.searchStr}" ${resp.data && resp.data.length > 0 ? '搜索结果' : '暂无结果'}`, 'Search')
    nextTick(() => {
      bus.emit('search', resp.data)
    })
  } else {
    openMessage('error', '搜索参数错误, 请重试!')
  }
  loading.hide()
}

const openFolderDialog = (groupId: number) => {
  data.needMoveToFolderGroupId = groupId
  data.dialogVisible = true
}

const moveGroupToFolder = async (folderId: number, fname: string) => {
  const reqData = new FormData()
  reqData.set('id', data.needMoveToFolderGroupId.toString())
  reqData.set('folderId', folderId ? folderId.toString() : 'null')
  loading.show()

  const resp = await moveGroupToFolderApi(reqData)
  if (resp && resp.code == SUCCESS_CODE) {
    data.dialogVisible = false
    openMessage('success', `已${ folderId == -1 ? '移出' : '移动到' }"${fname}"文件夹!`)
    getGroupAndFolder()
  } else {
    openMessage('error', `${ folderId == -1 ? '移出' : '移动到' }"${fname}"文件夹发生错误!`)
  }

  loading.hide()
}

const getGroupAndFolder = async () => {
  loading.show()
  const resp = await getGroupAndFolderApi()
  if (resp && resp.code == SUCCESS_CODE) {
    let allGroups: Group[] = resp.data.groups
    let folders: Folder[] = resp.data.folders
    data._groups = resp.data.groups
    data.groups = allGroups.filter(group => !group.folderId)
    data.folders = folders.map(folder => {
      folder.groups = allGroups.filter(group => group.folderId === folder.id)
      return folder
    })
    if (data.groups.length > 0) {
      changeCurGroup(data.groups[0].id, data.groups[0].gname, data.groups[0].icon)
    } else {
      changeCurGroup(-1, '', '')
    }
  }
  loading.hide()
}

bus.on('groupCountChange', (d: any) => {
  const group = data.groups.find(group => group.id === d.groupId)
  if (!group) return
  switch (d.type) {
    case 'add':
      group.count ++
      break
    case 'minus':
      group.count --
      break
    case 'move':
      const moveToGroup = data.groups.find(group => group.id === d.moveToGroupId)
      moveToGroup ? moveToGroup.count ++ : ''
      group.count --
  }
})
bus.on('reSearch', search)
onBeforeUnmount(() => {
  bus.off('groupCountChange')
  bus.off('reSearch')
})

getGroupAndFolder()
</script>

<style lang="scss" scoped>
.group-capsule {
  position: relative;
  padding-top: 10px;
  .scrollbar {
    padding-right: 10px;
    ::v-deep(.el-scrollbar__bar.is-horizontal) {
      display: none !important;
    }
  }

  .search-input {
    margin-bottom: 10px;
    ::v-deep(.el-input__wrapper) {
      border-right: 0;
    }
    ::v-deep(.el-input-group__append) {
      padding: 0;
      width: 40px;
    }
    .search-btn {
      width: 40px;
      height: 100%;
      padding: 0;
      @include transition('background', $default-transition-duration);
      &:hover {
        background: $hover-color;
      }
    }
  }

  .groups {
    text-align: left;
  }

  .folders {
    ::v-deep(.el-menu) {
      width: 100%;
      border-right: none;
      border-radius: $border-radius $border-radius 0 0;
      .el-sub-menu__title {
        height: 41px;
        padding-left: 6px;
      }
      .el-menu-item {
        height: 41px;
        line-height: 41px;
        margin-bottom: 5px;
        padding-left: 24px;
        padding-right: 15px;
        &:hover {
          background-color: transparent
        }
      }
    }
  }

  .bottom-bar {
    $btn-height: 45px;

    & {
      display: flex;
      justify-content: space-between;
      width: 100%;
      position: absolute;
      bottom: 0;
      left: 0;
      height: $btn-height;
      background-color: $background;
      padding-bottom: 5px;
    }

    .btn-popper{
      min-width: auto !important;
      text-align: center;
    }

    @mixin basic-btn {
      @include transition('background-color', $default-transition-duration);
      background-color: transparent;
      border: none;
      border-radius: 8px;
      &:hover {
        background-color: $hover-color;
      }
    }
    
    .addGroup-btn {
      width: 100%;
      height: 100%;
      justify-content: flex-start;
      font-size: $text-font-size;
      @include basic-btn();
      ::v-deep(.el-icon) {
        margin-right: 20px;
      }
    }
    .addFolder-btn {
      flex-grow: 0;
      height: 100%;
      width: $btn-height;
      margin-left: 0;
      font-size: $text-font-size;
      @include basic-btn();
    }
  }
}

.drawer-content {
  .folder-tag {
    margin-top: 20px;
    text-align: left;
    font-size: 14px;
    .title {
      margin-bottom: 18px;
    }

    .tag {
      cursor: pointer;
      margin: 0 5px 5px 0;
      &:hover, &.active {
        background-color: #ecf5ff;
        color: #409eff;
        border-color: #d9ecff;
      }
    }
  }
}

</style>
